// import Vue from 'vue'
import debounce from 'lodash.debounce'
import { deviceEnquire, DEVICE_TYPE } from '@/utils/device'
import { mapState } from 'vuex'

// const mixinsComputed = Vue.config.optionMergeStrategies.computed
// const mixinsMethods = Vue.config.optionMergeStrategies.methods

const mixin = {
  computed: {
    ...mapState({
      layoutMode: state => state.app.layout,
      navTheme: state => state.app.theme,
      primaryColor: state => state.app.color,
      colorWeak: state => state.app.weak,
      fixedHeader: state => state.app.fixedHeader,
      fixSiderbar: state => state.app.fixSiderbar,
      fixSidebar: state => state.app.fixSiderbar,
      contentWidth: state => state.app.contentWidth,
      autoHideHeader: state => state.app.autoHideHeader,
      sidebarOpened: state => state.app.sidebar,
      multiTab: state => state.app.multiTab
    })
  },
  methods: {
    isTopMenu() {
      return this.layoutMode === 'topmenu'
    },
    isSideMenu() {
      return !this.isTopMenu()
    }
  }
}

/**
 * 表单字段远程验证
 */
const asyncValidateMixin = {
  data() {
    return {
      canSubmit: true, // 远程验证请求过程中，表单不给提交，不然会有两个errorMessage
      validator: {},
      needVerify: {}
    }
  },

  methods: {
    $_asyncValidateMixin_init(fields) {
      this.validator = {}
      this.needVerify = {}
      for (const field of fields) {
        this.$set(this.validator, `${field.fieldName}ValidProps`, {
          validStatus: 'error',
          hasFeedback: false
        })
        this.$set(this.needVerify, field.fieldName, true)
        const validFunction = this.$_asyncValidateMixin_generator(field)
        this.$set(this.validator, `${field.fieldName}Validator`, debounce(validFunction, 500))
      }
    },

    $_asyncValidateMixin_generator(field) {
      const { fieldName, caller, extraParams } = field
      return (rule, value, callback) => {
        if (value) {
          this.canSubmit = false;
          caller(
            Object.assign({ fieldName, field: fieldName, key: fieldName, value: value }, typeof extraParams === 'function' ? extraParams() : extraParams)
          )
            .then(res => {
              this.$set(this.validator, `${fieldName}ValidProps`, {
                validStatus: 'error',
                hasFeedback: false
              })
              const { code, msg, message } = res
              if (code === 20001 || code === "unique_error_code" || code === 'iam.1021' || code === 'iam.1024' || code === 409) {
                this.$set(this.needVerify, fieldName, true)
                callback(msg || message)
              } else {
                // 凡是主动远程校验过的字段，都不再参与最终校验
                this.$set(this.needVerify, fieldName, false)
                callback()
              }
            })
            .catch(err => {
              this.$set(this.validator, `${fieldName}ValidProps`, {
                validStatus: 'error',
                hasFeedback: false
              })
            }).finally(() => {
              this.canSubmit = true;
            });
        } else {
          this.$set(this.needVerify, fieldName, true)
          this.$set(this.validator, `${fieldName}ValidProps`, {
            validStatus: 'error',
            hasFeedback: false
          })
          callback()
        }
      }
    },

    /**
     * 将不需要最终验证的字段过滤掉
     * @param { Object } values 表单字段值，包括参与校验的所有字段
     */
    $_asyncValidateMixin_fieldsFilter(values = null) {
      let fieldsError = {};
      if (!values) {
        const { getFieldsValue, getFieldsError } = this.form
        values = getFieldsValue()
        fieldsError = getFieldsError()
      }
      const fields = { ...values }
      for (const prop in this.needVerify) {
        if (this.needVerify.hasOwnProperty(prop) && !this.needVerify[prop] && !fieldsError[prop]) {
          delete fields[prop]
        }
      }

      return Object.keys(fields)
    },

    /**
     * 重置所有字段的 needVerify
     */
    $_asyncValidateMixin_resetFields() {
      for (const prop in this.needVerify) {
        if (this.needVerify.hasOwnProperty(prop) && !this.needVerify[prop]) {
          this.needVerify[prop] = true
        }
      }
    }
  }
}

const mixinDevice = {
  computed: {
    ...mapState({
      device: state => state.app.device
    })
  },
  methods: {
    isMobile() {
      return this.device === DEVICE_TYPE.MOBILE
    },
    isDesktop() {
      return this.device === DEVICE_TYPE.DESKTOP
    },
    isTablet() {
      return this.device === DEVICE_TYPE.TABLET
    }
  }
}

const AppDeviceEnquire = {
  mounted() {
    const { $store } = this
    deviceEnquire(deviceType => {
      switch (deviceType) {
        case DEVICE_TYPE.DESKTOP:
          $store.commit('TOGGLE_DEVICE', 'desktop')
          $store.dispatch('setSidebar', true)
          break
        case DEVICE_TYPE.TABLET:
          $store.commit('TOGGLE_DEVICE', 'tablet')
          $store.dispatch('setSidebar', false)
          break
        case DEVICE_TYPE.MOBILE:
        default:
          $store.commit('TOGGLE_DEVICE', 'mobile')
          $store.dispatch('setSidebar', true)
          break
      }
    })
  }
}

/**
 * 布局相关的尺寸
 */
const layoutMixin = {
  data() {
    return {
      layoutContentHeight: 0,
      layoutFooterHeight: 0,
      pageHeaderHeight: 0,
      layoutCardHeight: 0
    }
  },
  mounted() {
    this.initLayout()
    window.addEventListener('resize', this.initLayout)
  },
  beforeDestroy() {
    window.removeEventListener('resize', this.initLayout)
  },
  methods: {
    initLayout() {
      this.layoutContentHeight = 0
      this.layoutFooterHeight = 0
      this.pageHeaderHeight = 0

      this.$nextTick(() => {
        const layoutDom = document.querySelector('main.ant-layout-content')
        const footerDom = document.querySelector('footer.ant-layout-footer')
        const pageHeaderDom = layoutDom.querySelector('.page-header')
        this.layoutContentHeight = layoutDom ? layoutDom.offsetHeight : 0
        this.pageHeaderHeight = pageHeaderDom ? pageHeaderDom.offsetHeight : 0
        this.layoutFooterHeight = footerDom ? footerDom.offsetHeight : 0
        this.layoutCardHeight = this.layoutContentHeight - this.pageHeaderHeight
      })
    }
  }
}

/**
 * 操作modal
 */
const dialogMixin = {
  data() {
    return {
      // statusEnum: {
      //   edit: this.$t('common.edit'),
      //   add: this.$t('button.add')
      // },
      dialogModel: {},
      commonDlgProps: {
        maskClosable: false,
        keyboard: false
      }
    }
  },
  computed: {
    statusEnum() {
      return {
        edit: this.$t('common.edit'),
        add: this.$t('button.add')
      }
    }
  },
  methods: {
    operateDialog({ name, visible, status, onShown }) {
      this.$set(this.dialogModel, `${name}Status`, status)
      if (status) {
        this.$set(this.dialogModel, `${name}StatusText`, this.statusEnum[status])
      }
      this.$set(this.dialogModel, `${name}Visible`, visible)
      if (visible) {
        this.$nextTick(() => {
          if (typeof onShown === 'function') onShown()
        })
        // if (onShow) onShow();
        // if (status === 'edit') {
        // }
      }
    }
  }
}

/**
 * 拖拽改变尺寸
 * 目前只支持向右拖拉
 */
const resizableMixin = {
  data() {
    return {
      resizableMinWidth: 50,
      resizableMaxWidth: 800,
      resizableBaseWidth: 0,
      resizableX: 0,
      resizableY: 0,
      resizableMode: ''
    }
  },
  mounted() {
    const resizableBox = this.$el.querySelector('.resizable')
    if (!resizableBox) return

    this.resizableBaseWidth = resizableBox.offsetWidth

    const rightHandler = this.$el.querySelector('.resizable-handler-right')
    if (rightHandler) {
      rightHandler.addEventListener('mousedown', this.onMouseDown)
    }
  },
  beforeDestroy() {
    const rightHandler = this.$el.querySelector('.resizable-handler-right')
    if (rightHandler) {
      rightHandler.removeEventListener('mousedown', this.onMouseDown)
    }
  },
  methods: {
    // 需要主动设置宽度范围
    setup({ minWidth, maxWidth }) {
      if (minWidth) {
        this.resizableMinWidth = minWidth
      }
      if (maxWidth) {
        this.resizableMaxWidth = maxWidth
      }
    },
    onMouseDown(e) {
      const { clientX, clientY } = e
      this.resizableX = clientX
      this.resizableY = clientY
      this.resizableMode = e.target.className.split('-')[2]

      window.addEventListener('mousemove', this.onMouseMove)
      window.addEventListener('mouseup', this.onMouseUp)
    },
    onMouseMove(e) {
      const { clientX } = e
      const resizableBox = this.$el.querySelector('.resizable')
      if (this.resizableMode === 'right') {
        const targetWidth = this.resizableBaseWidth + clientX - this.resizableX
        if (targetWidth <= this.resizableMinWidth || targetWidth >= this.resizableMaxWidth) return
        resizableBox.style.width = `${targetWidth}px`
      }
    },
    onMouseUp() {
      const resizableBox = this.$el.querySelector('.resizable')
      this.resizableBaseWidth = resizableBox.offsetWidth
      window.removeEventListener('mousemove', this.onMouseMove)
      window.removeEventListener('mouseup', this.onMouseUp)
    }
  }
}

/**
 * 查询表单展开/收起mixin
 */
const tableSearchFormMixin = {
  data() {
    return {
      advanced: false
    };
  },
  methods: {
    toggleAdvanced() {
      this.advanced = !this.advanced;
    }
  }
};

export { mixin, asyncValidateMixin, AppDeviceEnquire, mixinDevice, layoutMixin, dialogMixin, resizableMixin, tableSearchFormMixin }
